﻿#include "myThread.h"
#include <QFile>
#include<QApplication>

typedef struct
{
	HWND hWnd;
	DWORD dwPid;
}WNDINFO;
int numScreen = 0;
RECT Srect[2];
myThread::myThread(QObject *parent)
	: QThread(parent)
{

}

BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor,//回掉函数，用于查询保存屏幕信息
	HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
{
	static BOOL first = TRUE;   //标志
	//保存显示器信息
	MONITORINFO monitorinfo;
	monitorinfo.cbSize = sizeof(MONITORINFO);
	//获得显示器信息，将信息保存到monitorinfo中
	GetMonitorInfo(hMonitor, &monitorinfo);
	//若检测到主屏
	if (monitorinfo.dwFlags == MONITORINFOF_PRIMARY)
	{
		if (first)  //第一次检测到主屏
		{
			first = FALSE;
			numScreen = 1;
			//将显示器的分辨率信息保存到rect
			Srect[0] = monitorinfo.rcMonitor;
			return TRUE;
		}
		else //第二次检测到主屏,说明所有的监视器都已经检测了一遍，故可以停止检测了
		{
			first = TRUE;    //标志复位
			return FALSE;    //结束检测
		}
	}
	Srect[numScreen] = monitorinfo.rcMonitor;
	numScreen++;
	return TRUE;
}
BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)//查询窗口句柄
{
	WNDINFO* pInfo = (WNDINFO*)lParam;
	DWORD dwProcessId = 0;
	GetWindowThreadProcessId(hWnd, &dwProcessId);
	if (dwProcessId == pInfo->dwPid)
	{
		pInfo->hWnd = hWnd;
		return FALSE;
	}
	return TRUE;
}

HWND GetHwndByProcessId(DWORD dwProcessId)//根据进程id查询窗口句柄
{
	WNDINFO info = { 0 };
	info.hWnd = NULL;
	info.dwPid = dwProcessId;
	EnumWindows(EnumWindowsProc, (LPARAM)&info);
	return info.hWnd;
}
HWND GetHwndByPid(DWORD dwProcessID)
{
	//返回Z序顶部的窗口句柄  
	HWND hWnd = ::GetTopWindow(0);
	while (hWnd)
	{
		DWORD pid = 0;
		//根据窗口句柄获取进程ID  
		DWORD dwTheardId = ::GetWindowThreadProcessId(hWnd, &pid);
		if (dwTheardId != 0)
		{
			if (pid == dwProcessID)
			{
				return hWnd;
			}
		}
		//返回z序中的前一个或后一个窗口的句柄  
		hWnd = ::GetNextWindow(hWnd, GW_HWNDNEXT);
	}
	return hWnd;
}

HWND reGetHwnd(std::string path)
{
	int ID = 0;
	HWND hwnd = NULL;
	//进程列举  
	std::string exeName = path + ".exe";
	const char *cPath = path.c_str();
	LeiJiaWebHttp::GetInstance()->writeLog(QString(QLatin1String(cPath)));
	HANDLE hSnApshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
	if (hSnApshot != INVALID_HANDLE_VALUE)
	{
		PROCESSENTRY32 te = { sizeof(te) };
		BOOL f0k = Process32First(hSnApshot, &te);
		for (; f0k; f0k = Process32Next(hSnApshot, &te))
		{
			wprintf(L"Pid: %d %s\n", te.th32ProcessID, te.szExeFile);
			int size = WideCharToMultiByte(CP_ACP, 0, te.szExeFile, -1, NULL, 0, NULL, NULL);
			char *ch = new char[size + 1];
			if (WideCharToMultiByte(CP_ACP, 0, te.szExeFile, -1, ch, size, NULL, NULL))
			{
				_strlwr_s(ch, strlen(ch) + 1); // 将进程名称转换成小写
				if (strstr(ch, cPath))
				{
					LeiJiaWebHttp::GetInstance()->writeLog(QString(QLatin1String(ch)));
					ID = te.th32ProcessID;
					const char* c_exeName = exeName.c_str();
					//if (memcmp(ch, c_exeName, strlen(ch)) != 0)
					//{
					//	HANDLE hProcess;
					//	hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, ID);
					//	WaitForInputIdle(hProcess, INFINITE);//等待程序启动完毕
					//	CloseHandle(hProcess);
					//	CloseHandle(hSnApshot);
					//	return GetHwndByProcessId(ID);//获取游戏窗口句柄
					//}
					//if (memcmp(ch, c_exeName, strlen(ch)) == 0)
					//{
					//	HANDLE hProcess;
					//	hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, ID);
					//	WaitForInputIdle(hProcess, INFINITE);//等待程序启动完毕
					//	CloseHandle(hProcess);
					//	CloseHandle(hSnApshot);
					//	return GetHwndByProcessId(ID);//获取游戏窗口句柄
					//}			
	
					hwnd = GetHwndByProcessId(ID);//获取游戏窗口句柄
					if (hwnd != NULL)
					{
						LeiJiaWebHttp::GetInstance()->writeLog("not null");
						LeiJiaWebHttp::GetInstance()->writeLog(QString(QLatin1String(ch)));
						break;
					}
				}
			}
		}
	}
	CloseHandle(hSnApshot);
	return hwnd;
}
void  myThread::DLLStartPro(char* cPath)
{
	try{
		//保存显示器信息
		MONITORINFO monitorinfo;
		monitorinfo.cbSize = sizeof(MONITORINFO);
		const int loopNmu = 2000;
		EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, 0);//查询显示器个数

		PROCESS_INFORMATION pro_info; //进程信息  
		STARTUPINFO sti; //启动信息  
		// 初始化两个结构体  
		ZeroMemory(&pro_info, sizeof(PROCESS_INFORMATION));
		ZeroMemory(&sti, sizeof(STARTUPINFO));

		_bstr_t bstr(cPath);
		LPTSTR lptstr = (LPTSTR)bstr;
		CreateProcess(lptstr, NULL, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &sti, &pro_info);//启动游戏进程
		printf("%s\n", cPath);
		HWND hwnd = NULL;
		HWND nhwnd = NULL;
		DWORD rc = WaitForInputIdle(pro_info.hProcess, 20000);//等待程序启动完毕
		printf("%s%d\n", "开启进程ID:", pro_info.dwProcessId);
		char* str;
		LPTSTR buffer = new   TCHAR[255];
		if (rc == 0)
		{
			hwnd = GetHwndByProcessId(pro_info.dwProcessId);//获取游戏窗口句柄
			int aa = GetClassName(hwnd, buffer, 255);
			str = (char*)(LPTSTR)buffer;
			if (hwnd == NULL)
			{
				LeiJiaWebHttp::GetInstance()->writeLog("hwnd is null!reGetHwnd");
				QTime dieTime = QTime::currentTime().addSecs(30);//延时30秒
				while (QTime::currentTime() < dieTime)
				{
					//QCoreApplication::processEvents(QEventLoop::AllEvents, 100);//使程序保持响应
				}
				printf("%s\n", "hwnd is null!reGetHwnd");
				std::string path;
				path = m_nGame.toLower().toStdString();
				hwnd = reGetHwnd(path);//获取游戏窗口句柄
				if (hwnd == NULL)
				{
					QStringList list = LeiJiaWebHttp::GetInstance()->getSpecialGamesList();
					for (int i = 0; i < list.count(); i++)
					{
						LeiJiaWebHttp::GetInstance()->writeLog(list.at(i));
						path = list.at(i).toLower().toStdString();
						hwnd = reGetHwnd(path);//获取游戏窗口句柄
						if (hwnd != NULL)
							break;
					}
				}
			}
		}
		else if (rc == WAIT_TIMEOUT)
		{
			LeiJiaWebHttp::GetInstance()->writeLog("WAIT_TIMEOUT");
			hwnd = GetHwndByProcessId(pro_info.dwProcessId);//获取游戏窗口句柄
			if (hwnd == NULL)
			{
				LeiJiaWebHttp::GetInstance()->writeLog("hwnd is null!reGetHwnd");
				QTime dieTime = QTime::currentTime().addSecs(30);
				while (QTime::currentTime() < dieTime)
				{
					//QCoreApplication::processEvents(QEventLoop::AllEvents, 100);//使程序保持响应
				}
				printf("%s\n", "hwnd is null!reGetHwnd");
				std::string path;
				path = m_nGame.toLower().toStdString();
				hwnd = reGetHwnd(path);//获取游戏窗口句柄
				if (hwnd == NULL)
				{
					QStringList list = LeiJiaWebHttp::GetInstance()->getSpecialGamesList();
					for (int i = 0; i < list.count(); i++)
					{
						path = list.at(i).toLower().toStdString();
						hwnd = reGetHwnd(path);//获取游戏窗口句柄
						if (hwnd != NULL)
							break;
					}
				}
			}
		}
		else if (rc == WAIT_FAILED)
		{
			LeiJiaWebHttp::GetInstance()->writeLog("WAIT_FAILED");
		}
		if (numScreen != 2)
		{
			printf("%s\n", "find screen again!");
			EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, 0);
		}
		if (hwnd == NULL)
			LeiJiaWebHttp::GetInstance()->writeLog("hwnd is null!");
		if (!::MoveWindow(hwnd, Srect[1].left, Srect[1].top, Srect[1].right - Srect[1].left, Srect[1].bottom - Srect[1].top, TRUE))
		{
			LeiJiaWebHttp::GetInstance()->writeLog("not move");
		}
		ShowWindow(hwnd, SW_MAXIMIZE);//窗口最大化
		if (m_gameResult.IsSpecial)
		{
			LeiJiaWebHttp::GetInstance()->writeLog("IsSpecial");
			QTime dieTime = QTime::currentTime().addSecs(10);// 延时10秒
			while (QTime::currentTime() < dieTime)
			{
			}
			nhwnd = ::FindWindow(buffer, NULL);
			if (!::MoveWindow(nhwnd, Srect[1].left, Srect[1].top, Srect[1].right - Srect[1].left, Srect[1].bottom - Srect[1].top, TRUE))
			{
				LeiJiaWebHttp::GetInstance()->writeLog("not move");
			}
		}
	}
	catch (...)
	{
		LeiJiaWebHttp::GetInstance()->writeLog("error");
	}
}

myThread::~myThread()
{
}

void myThread::setData(char* c_path, GameResult result)
{
	c_starPath = c_path;
	m_gameResult = result;
}
void myThread::setGameName(QString name)
{
	m_nGame = name;
}
void myThread::run()
{
	DLLStartPro(c_starPath);//开启游戏进程
	LeiJiaWebHttp::GetInstance()->writeLog("run Finished");
}